package model;

import javax.swing.JPanel;
import javax.swing.JLabel;

import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;

import java.util.*;

public class Ressources extends Observable {
	
    /** Types internes */
    public static enum Type { DOLLARS, GOODS, PERSONS };

    /** Attributs */
    private NavigableMap<Type, Double> m_available;
    private NavigableMap<Type, Double> m_limits;

    /** Constructeurs */
    public Ressources(Ressources ressources) {
        m_available = new TreeMap<Type, Double>(ressources.m_available);
        m_limits = new TreeMap<Type, Double>(ressources.m_limits);
    }

    public Ressources() {
        m_available = new TreeMap<Type, Double>();
        m_limits = new TreeMap<Type, Double>();
    }
	
    /** Accesseurs */
    public double getQuantity(Type type) { 
        Double quantity = m_available.get(type);
        if (quantity == null) return 0;
        else return quantity.doubleValue();
    }

    public double getLimit(Type type) { 
        Double limit = m_limits.get(type);
        if (limit == null) return -1;
        else return limit.doubleValue();
    }

    /** Mutateurs */
    public void set(Type type, double quantity) {
        setQuantity(type, quantity); 
    }

    public void set(Type type, double quantity, double limit) {
        setQuantity(type, quantity);
        setLimit(type, limit);
    }

    public void setQuantity(Type type, double quantity) {
        assert quantity >= 0 : "la quantite d'une ressource doit etre positive";
        assert quantity <= getLimit(type) : "la quantite de la ressource doit etre inferieur a la limite";
        m_available.put(type, quantity);
        setChanged();
        notifyObservers();
    }

    public void setLimit(Type type, double limit) {
        assert limit > 0 : "la limite d'une ressource doit etre positive";
        assert getQuantity(type) <= limit : "la quantite de la ressource doit etre inferieur a la limite";
        m_limits.put(type, limit);
        setChanged();
        notifyObservers();
    }

    public void unsetLimit(Type type) { m_limits.remove(type); }
	
    /** Predicats */
    public boolean isAvailable(Type type) { return m_available.get(type) != null; }

    public boolean isLimited(Type type) { return m_limits.get(type) != null; }

    public boolean isEquals(Ressources ressources) { return false; } // ToDo

    /** Methodes */
    public void add(Type type, double quantity) 
    { setQuantity(type, getQuantity(type) + quantity); }

    public void remove(Type type, double quantity) 
    { setQuantity(type, getQuantity(type) - quantity); }

    public void transferTo(Ressources ressource, Type type, double quantity) {
        remove(type, quantity);
        ressource.add(type, quantity);
    }

    public void incLimit(Type type, double quantity) 
    { setLimit(type, getLimit(type) + quantity); }

    public void decLimit(Type type, double quantity)
    { setLimit(type, getLimit(type) - quantity); }

    public NavigableSet<Type> types() {
        return m_available.navigableKeySet();
    }

}